(function (window) {
    //常量
    var consts = {
        widgetType: {
            data: "data",
            dom: "dom"
        },
        invokeType: {
            update: "update",
            eventClick: "eventClick",
            init: "init"
        },
        syncType: {
            socket: "socket",
            sockjs: "sockjs",
            winext: "winext"
        },
        go_external_invoke: false
    }
    //工具
    var tools = {
        randomNum: function (s) {
            s = s || 10;
            return Math.floor(Math.random() * s);
        },
        randomPrefix: function (prefix, len) {
            len = len || 10;
            var name = prefix + "_";
            for (var i = 0; i < len; i++) {
                name += this.randomNum();
            }
            return name;
        }
    }
    /**
     * 组件绑定对象
     * {
     *     componentName:{//组件名称
     *         component: component,//当前组件对象
     *         widgets:{//组件绑定的控件
     *              widgetName1:{
     *                  type: 控件类型 data or dom
     *                  value: 控件值 interface{}
     *                  cb: 回掉函数
     *                  fn: 执行函数
     *              }
     *         }
     *     }
     * }
     */
    var Widget = function (component, id, type, value, cb, fn) {
        this.component = component;
        this.id = id;
        this.type = consts.widgetType.data || type;
        this.value = value;
        this.cb = cb;
        this.fn = fn;
        return this;
    }
    Widget.prototype.setValue = function (value) {
        this.value = value;
    }

    //组件
    var Component = function (name, vue, widgets) {
        this.name = name;
        this.vue = vue;
        this.widgets = widgets || {};
    }

    Component.prototype.setWidget = function (widgetId, value, cb, fn) {
        if (this.widgets.hasOwnProperty(widgetId)) {
            this.widgets[widgetId].setValue(value);
        } else {
            this.widgets[widgetId] = new Widget(this, widgetId, consts.widgetType.data, value, cb, fn);
        }
    }
    Component.prototype.getWidget = function (widgetId) {
        return this.widgets[widgetId];
    }

    var _components = function () {
        this.components = {};
    }
    //设置组件到组件管理器
    _components.prototype.setComponent = function (componentName, newVue) {
        if (!componentName) {
            return
        }
        if (this.components.hasOwnProperty(componentName)) {
            var component = this.getComponent(componentName);
            component.vue = newVue;
        } else {
            this.components[componentName] = new Component(componentName, newVue);
        }
    }
    _components.prototype.getComponent = function (componentName) {
        return this.components[componentName];
    }
    /**
     *  方式 window.external.invoke
     */
    _components.prototype.invoke = function (type, componentName, widgetId, value) {
        var rpcJson;
        if (type === consts.invokeType.init) {
            rpcJson = JSON.stringify({type: type});
            try {
                window.external.invoke(rpcJson);
                consts.go_external_invoke = true;
            } catch (e) {
                consts.go_external_invoke = false;
                console.log(rpcJson);
            }
        } else {
            var component = this.getComponent(componentName);
            if (component) {
                console.log(component);
                var widget = component.getWidget(widgetId);
                console.log(widget);
                if (widget) {
                    widget.setValue(value);
                    rpcJson = JSON.stringify({
                        type: type,
                        componentName: componentName,
                        widgetId: widgetId,
                        value: value
                    });
                    if (consts.go_external_invoke) {
                        window.external.invoke(rpcJson);
                    } else {
                        console.log(rpcJson);
                    }
                }
            }
        }
    }
    //创建唯一组件维护对象
    var components = new _components();

    //对外暴露的 bind 函数
    var BIND = function () {
        return this;
    }
    /**
     * go 控件需要同步绑定注册页面控件上
     * @param componentName 组件名称
     * @param widgetId 控件ID 或 data的名称
     * @param value 值
     */
    BIND.prototype.bind = function (componentName, widgetId, value) {
        alert(componentName + "  " + widgetId);
        if (!componentName || !widgetId) {
            return
        }
        var component = components.getComponent(componentName);
        if (component) {
            component.setWidget(widgetId, value);
        } else {
            components.setComponent(componentName);
            component = components.getComponent(componentName);
            component.setWidget(widgetId, value);
        }
    }
    BIND.prototype.getComponent = function (componentName) {
        return components.getComponent(componentName);
    }
    BIND.prototype.getComponentAll = function () {
        return components.components;
    }
    // vue 初始化后 在 created 函数中调用
    BIND.prototype.sync = function (component) {
        var componentName = component.$options.name;
        if (!componentName) {
            console.log("组件名字为空");
            return
        }
        components.setComponent(componentName, component);
        for (var key in component.$data) {
            (function (key, componentName) {
                component.$watch(key, {
                    handler: function (newValue, oldValue) {
                        console.log("同步改变数据=>:", name, key, newValue, oldValue);
                        components.invoke(consts.invokeType.update, componentName, key, newValue);
                    },
                    deep: true
                });
            }(key, componentName));
        }
    }
    //Go代码回调函数 将GO修改的数据同步到JS
    BIND.prototype.GoSyncJS = function (componentName, widgetId, value) {
        var component = this.getComponent(componentName);
        alert("GoSyncJS: " + componentName + " " + widgetId + " " + value);
        if (component) {
            var vue = component.vue;
            console.log(componentName, widgetId, value);
        }
    }
    //Go代码回调函数 JS Invoke GO 之后，GO返回的结果
    BIND.prototype.GoInvokeResult = function (type, componentName, widgetId, value) {
        alert("GoInvokeResult: " + componentName + " " + widgetId + " " + value);
    }
    window.GoBind = new BIND();
    //页面初始化通知GO同步 Bind
    components.invoke(consts.invokeType.init, "", "", "");
}(window));
